﻿using System;
using System.Diagnostics;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Hosting;
using Owin;
using Wolfpack.Periscope.Core.Extensions;
using Wolfpack.Periscope.Core.Infrastructure;
using Wolfpack.Periscope.Core.Interfaces;
using Wolfpack.Periscope.Core.Interfaces.Events;

namespace Wolfpack.Periscope.Core.Plugins
{
    public class SignalRPlugin : IDashboardPlugin
    {
        private IDisposable _appHost;

        private readonly IDashboard _dashboard;
        private readonly TinySubscriptionManager _subscriptionManager;

        public SignalRPlugin(IDashboard dashboard)
        {
            _dashboard = dashboard;
            _subscriptionManager = _dashboard.Infrastructure.MessageBus.CreateSubscriptionManager();
        }

        public void Initialise()
        {
            _subscriptionManager.AddHandler<WidgetUpdateCommand>(BroadcastWidgetUpdate)
                .AddHandler<PanelRotateNowEvent>(BroadcastPanelRotateNowCommand)
                .AddHandler<PanelConfigurationChangedEvent>(BroadcastPanelConfigurationChangedCommand)
                .AddHandler<WidgetResizedEvent>(BroadcastWidgetResizedCommand)
                .AddHandler<WidgetAddedEvent>(BroadcastWidgetAddedCommand);
        }

        public void Start()
        {
            // TODO: pass this in as ctor param
            _appHost = WebApp.Start<Startup>(string.Format("http://{0}:805/", Environment.MachineName));
        }

        private void BroadcastWidgetUpdate(WidgetUpdateCommand msg)
        {
            GlobalHost.ConnectionManager.GetHubContext<Dashboard>().Clients.All
                .widgetUpdateCommand(msg.Content);
        }

        private void BroadcastPanelRotateNowCommand(PanelRotateNowEvent msg)
        {
            GlobalHost.ConnectionManager.GetHubContext<Dashboard>().Clients.All
                .panelRotateCommand(new { PanelId = msg.Content.Id });
        }

        private void BroadcastPanelConfigurationChangedCommand(PanelConfigurationChangedEvent msg)
        {
            GlobalHost.ConnectionManager.GetHubContext<Dashboard>().Clients.All
                .panelConfigChangedCommand(msg.Content);
        }
        private void BroadcastWidgetResizedCommand(WidgetResizedEvent msg)
        {
            GlobalHost.ConnectionManager.GetHubContext<Dashboard>().Clients.All
                .widgetResizedCommand(msg.Content);
        }
        private void BroadcastWidgetAddedCommand(WidgetAddedEvent msg)
        {
            GlobalHost.ConnectionManager.GetHubContext<Dashboard>().Clients.All
                .widgetAddedCommand(msg.Content);
        }

        public void Dispose()
        {            
            _subscriptionManager.Dispose();
            _appHost.Dispose();
        }
    }

    public class Dashboard : Hub
    {
        public override System.Threading.Tasks.Task OnConnected()
        {
            Debug.WriteLine("Dashboard Connected! (SignalR client)");
            return base.OnConnected();
        }
    }

    internal class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Map("/signalr", map =>
            {
                // Setup the cors middleware to run before SignalR.
                // By default this will allow all origins. You can 
                // configure the set of origins and/or http verbs by
                // providing a cors options with a different policy.
                map.UseCors(CorsOptions.AllowAll);

                var hubConfiguration = new HubConfiguration
                {
                    // You can enable JSONP by uncommenting line below.
                    // JSONP requests are insecure but some older browsers (and some
                    // versions of IE) require JSONP to work cross domain
                    // EnableJSONP = true
                };

                // Run the SignalR pipeline. We're not using MapSignalR
                // since this branch is already runs under the "/signalr"
                // path.
                map.RunSignalR(hubConfiguration);
            });
        }
    }
}